home *** CD-ROM | disk | FTP | other *** search
/ System Booster / System Booster.iso / Archives / HardwareProjects / VideoText.lha / VideoText4.2 / source / s_i2cbusIO.s < prev    next >
Encoding:
Text File  |  1994-10-03  |  6.2 KB  |  208 lines

  1. ;=============================================================================
  2. ; s_i2cbusIO.s: Assembler-Version der KICK-Pascal Prozedur i2cbusIO (seriell)
  3. ; Parameterübergabe (auf dem Stack):
  4. ;  12(A7).B: logische Busadresse           -> D0
  5. ;   8(A7).L: Zeiger auf den I/O-Puffer     -> A0
  6. ;   6(A7).W: Anzahl zu übertragender Daten -> D1
  7. ;   4(A7).W: Zeitschleifen-Durchgänge      -> D5
  8. ; Rückgabewert:
  9. ;   D0.W: Status, Bedeutung s. u.
  10. ;-----------------------------------------------------------------------------
  11. ; Funktionsweise:
  12. ; Startet den I²C-Bus und spricht den in D0 bezeichneten Chip an. Wenn D1
  13. ; negativ ist, werden -D1 Bytes vom Bus geholt und ab Adresse A0 im Speicher
  14. ; abgelegt, sonst +D1 Bytes ab A0 über den Bus abgeschickt. Die Busadresse
  15. ; (D0) wird dabei automatisch zur Schreib- bzw. Leseadresse gemäß I²C-Bus-
  16. ; Konvention korrigiert. Abschließend wird der I²C-Bus wieder gestoppt.
  17. ; Anmerkungen:
  18. ; 1. Die über D5 bestimmte Zeitschleife soll den Bustakt bremsen, wobei
  19. ;    maximal 100 kHz zulässig sind, "zu langsam" gibt es dagegen am I²C-Bus
  20. ;    NICHT. Auf normalen Amigas sollte D5=0 sein.
  21. ; 2. Mehr Bytes zum Lesen anzufordern, als der bereitgestellte Puffer fassen
  22. ;    kann, ist ein Fehler, der nicht erkannt werden kann und wahrscheinlich
  23. ;    mit einem GURU endet.
  24. ; 3. Bedeutung des Statusworts:
  25. ;      0 = fehlerfreie Übertragung
  26. ;      1 = unquittierte Daten
  27. ;      2 = angesprochener Chip antwortet nicht
  28. ;      3 = gesendete Daten wurden (ohne erkennbares Schema) zerstört
  29. ;      4 = gesendete Daten zu Null verfälscht
  30. ;      5 = gesendete Daten zu Einsen verfälscht
  31. ;=============================================================================
  32.  
  33. ; interne Registerverwendung:
  34. ; D0: Datenbyte, das gesendet oder empfangen wird
  35. ; D1: Anzahl zu übertragende Bytes
  36. ; D2: Zähler über gesendete Bytes
  37. ; D3: Zähler über 8 Bits
  38. ; D4: Zähler für Zeitschleife
  39. ; D5: Grenze für Zeitschleife
  40. ; D6: Kontrollbyte beim Senden
  41. ; A0: Pufferzeiger
  42. ; A1: Adresse des CIA-Ports
  43.  
  44. CIABPRA  = $BFD000
  45. CIABDDRA = $BFD200
  46. ClkOutBit  = 6 ; CIAB_COMRTS
  47. ClkInBit   = 4 ; CIAB_COMCTS
  48. DataOutBit = 7 ; CIAB_COMDTR
  49. DataInBit  = 5 ; CIAB_COMCD
  50.  
  51. DELAY MACRO
  52.   move.w d5,d4
  53. loop\@ dbf d4,loop\@
  54.   ENDM
  55.  
  56. ; Linker-Information:
  57.   xdef s_i2cbusIO
  58.  
  59. s_i2cbusIO:
  60. ; Parameter vom Stack holen:
  61.   move.b 12(a7),d0
  62.   move.l 8(a7),a0
  63.   move.w 6(a7),d1
  64.   move.w 4(a7),a1
  65.  
  66. test:
  67. ; veränderte Register retten: D2,D3,D4,D5,D6
  68.   movem.l d2-d6,-(a7)
  69.  
  70. ; einen der Parameter noch ins richtige Register packen:
  71.   move.w a1,d5
  72.  
  73. ; CIA-Datenrichtungsregister initialisieren
  74.   move.l #CIABDDRA,a1
  75.   bset #ClkOutBit,(a1)
  76.   bset #DataOutBit,(a1)
  77.   bclr #ClkInBit,(a1)
  78.   bclr #DataInBit,(a1)
  79.  
  80. ; Bus in Ruhezustand bringen: DATA=HI, CLK=HI
  81.   move.l #CIABPRA,a1
  82.   bset #DataOutBit,(a1)
  83.   bset #ClkOutBit,(a1)
  84.  
  85. ; Bus starten (Protokollverletzung H->L): DATA=LO, CLK=LO
  86.   DELAY
  87.   bclr #DataOutBit,(a1)
  88.   DELAY
  89.   bclr #ClkOutBit,(a1)
  90.   DELAY
  91.  
  92. ; Soll ich senden oder empfangen?
  93.   bclr #0,d0 ; Voreinstellung: Adresse als Sendeadresse
  94.   tst.w d1
  95.   bpl .zweck
  96.     bset #0,d0   ; Adresse als Leseadresse
  97. .zweck:
  98.  
  99. ; Daten senden, mindestens die Adresse, und evtl. <D1> weitere Bytes
  100. ; (Adressbyte steht bereits in D0):
  101.   clr.w d2 ; Bytezähler auf Null
  102. SendLoop: ; das in D0 enthaltene Byte über den Bus schicken, MSB zuerst
  103.   moveq.b #7,d3
  104.   clr.b d6; Protokollbyte
  105. SBitLoop:
  106.   btst d3,d0
  107.   beq .SL1
  108.   bset #DataOutBit,(a1) ; "1" senden
  109.   bra .SL2
  110. .SL1 bclr #DataOutBit,(a1) ; "0" senden
  111. .SL2: ; Einen CLK-Impuls geben, um das Bit lesen zu lassen
  112.   bset #ClkOutBit,(a1)
  113.   DELAY
  114.   btst #DataInBit,(a1)
  115.   beq .SL3 ; SDA ist "0", nichts tun
  116.   bset d3,d6 ; SDA ist "1", Bit im Protokollbyte setzen
  117. .SL3 bclr #ClkOutBit,(a1)
  118.   DELAY
  119.   dbf d3,SBitLoop
  120.   cmp.b d6,d0
  121.   bne SendErr ; Protokollbyte<>gesendetes Byte!
  122. ; 9. CLK-Impuls, um Quittungsbit zu lesen:
  123.   bset #DataOutBit,(a1) ; sonst liest man nur das eigene LO!
  124.   bset #ClkOutBit,(a1)
  125.   DELAY
  126.   btst #DataInBit,(a1)
  127.   bne AckErr ; DATA=HI -> NAK, Übertragung abbrechen
  128.   bclr #ClkOutBit,(a1)
  129.   DELAY
  130. ; genug Daten gesendet?
  131.   addq.w #1,d2 ; gesendetes Byte zählen
  132.   cmp.w d1,d2 ; dran denken: Adressbyte wurde mitgezählt
  133.   bgt SendEnd ; ja, fertig (schließt auch den Fall d1<0 ein)
  134.   move.b (a0)+,d0 ; nein, Byte aus Puffer holen
  135.   bra SendLoop
  136. AckErr:
  137.   moveq.w #1,d0 ; Status = unquittiertes Byte
  138.   tst.w d2 ; das wievielte Byte war es?
  139.   bne BusStop ; irgendeins
  140.   moveq.w #2,d0 ; sonst: Status = unquittiertes Adressbyte
  141.   bra BusStop
  142. SendErr:
  143.   bset #ClkOutBit,(a1) ; Noch eben das Quittungsbit anfordern, auch wenn
  144.   DELAY                ; das Bit selbst jetzt egal ist.
  145.   bclr #ClkOutBit,(a1) ; Sonst könnte aber die Stoppbedingung am Bus
  146.   DELAY                ; verloren gehen!
  147.   moveq.w #5,d0 ; Status = Daten zu 1 verfälscht
  148.   cmp.b #255,d6 ; stimmt das überhaupt?
  149.   beq BusStop ; ja
  150.   moveq.w #4,d0 ; Status = Daten zu 0 verfälscht
  151.   cmp.b #0,d6 ; stimmt?
  152.   beq BusStop ; ja
  153.   moveq.w #3,d0 ; Status = Daten irgendwie zerstört
  154.   bra BusStop
  155. SendEnd:
  156.   tst.w d1
  157.   bmi RecvLoop ; es sollen auch noch Bytes empfangen werden
  158.   moveq.w #0,d0 ; Status = OK
  159.   bra BusStop
  160.  
  161. ; soviele Bytes empfangen, wie in A1 angegeben:
  162. RecvLoop: ; ein Byte vom Bus holen, MSB zuerst, und in D0 zusammensetzen
  163.   bset #DataOutBit,(a1) ; DATA-Leitung freigeben
  164.   clr.b d0
  165.   moveq.b #7,d3
  166. RBitLoop:
  167. ; Einen CLK-Impuls geben, ein Bit lesen:
  168.   bset #ClkOutBit,(a1)
  169.   DELAY
  170.   btst #DataInBit,(a1)
  171.   beq .RL1 ; "0" empfangen, nichts tun
  172.   bset d3,d0 ; "1" empfangen, entsprechendes Bit setzen
  173. .RL1 bclr #ClkOutBit,(a1)
  174.   DELAY
  175.   dbf d3,RBitLoop
  176.   move.b d0,(a0)+ ; Byte im Puffer speichern
  177. ; Quittierungsbit senden, "0", außer nach dem letzten Byte:
  178.   addq.w #1,d1 ; empfangenes Byte zählen
  179.   beq .RL2 ; letztes Byte, DATA auf HI lassen
  180.   bclr #DataOutBit,(a1) ; nein, DATA=LO
  181. .RL2: ; CLK-Impuls geben, Quittungsbit lesen lassen:
  182.   bset #ClkOutBit,(a1)
  183.   DELAY
  184.   bclr #ClkOutBit,(a1)
  185.   DELAY
  186. ; alle Daten empfangen?
  187.   tst.w d1
  188.   bne RecvLoop ; nein, weitermachen
  189.   moveq.w #0,d0 ; Status: OK
  190.  
  191. BusStop: ; I²C-Bus stoppen (Protokollverletzung L->H): CLK=HI, DATA=HI
  192. ; zunächst noch CLK=LO, DATA=LO sicherstellen:
  193.   bclr #ClkOutBit,(a1)
  194.   bclr #DataOutBit,(a1)
  195.  
  196.   DELAY
  197.   bset #ClkOutBit,(a1)
  198.   DELAY
  199.   bset #DataOutBit,(a1)
  200.   DELAY
  201.  
  202. ; gerettete Register zurückholen: D2,D3,D4,D5,D6
  203.   movem.l (a7)+,d2-d6
  204.   rts
  205.  
  206.   end
  207.  
  208.